<template>
    <el-tooltip
        class="box-item"
        popper-class="popover-scroll"
        :content="tipContent"
        placement="top-end"
        :show-arrow="false"
        transition="q-zoom"
    >
        <div ref="toolRef" class="tool-box">
            <div class="tool-right">
                <div class="tool-icon">
                    <el-popover
                        :visible="visible"
                        :placement="placement"
                        :show-arrow="showArrow"
                        width="200px"
                        class="popover-scroll"
                        popper-style="padding: 0;border-radius: 8px;transform-origin: top right;"
                        transition="scale"
                    >
                        <template #reference>
                            <q-icon
                                icon-class="a-zidingyipeizhi1"
                                class-name="custom-tooltip"
                                :class="{ 'is-disabled': disabled }"
                                size="14px"
                                color="#8c8c8c"
                                @click.stop="handleVisible"
                            />
                        </template>
                        <div class="setting-list" @click.stop>
                            <div class="setting-head">
                                自定义配置
                                <span @click="handleReset">恢复默认</span>
                            </div>
                            <div class="setting-group">
                                <div class="setting-top">冻结列表</div>
                                <div class="setting-affix">
                                    <el-checkbox v-model="affixChecked" label="" size="large" />
                                    <div class="setting-affix__input" @click.stop>
                                        冻结至
                                        <el-input-number
                                            v-model="affixColumn"
                                            :min="1"
                                            :max="max"
                                            :controls="false"
                                            :disabled="!affixChecked"
                                            style="
                                                width: 40px;
                                                height: 28px;
                                                margin: 0 4px;
                                                text-align: center;
                                            "
                                            @blur="handleAffixColumn"
                                        />
                                        列
                                    </div>
                                </div>
                            </div>
                            <div class="setting-group">
                                <div class="setting-top">自定义展示字段</div>
                                <el-checkbox-group
                                    v-model="checkList"
                                    class="setting-checkbox--box"
                                    @change="handleCheckedChange"
                                >
                                    <div class="setting-checkbox-group">
                                        <draggable
                                            v-model="tableHeadList"
                                            animation="300"
                                            item-key="modelKey"
                                            handle=".move"
                                            filter=".unmove"
                                            :move="checkMove"
                                            :component-data="{ name: 'fade' }"
                                            @change="handleDragChange"
                                        >
                                            <template #item="{ element }">
                                                <div
                                                    :key="element.modelKey"
                                                    class="setting-checkbox-option"
                                                >
                                                    <q-icon
                                                        icon-class="a-tuozhuai1"
                                                        size="18px"
                                                        color="#dfdede"
                                                        :class="[
                                                            'custom-tooltip',
                                                            'move',
                                                            {
                                                                unmove:
                                                                    element.fixed ||
                                                                    excludeLabel.includes(
                                                                        element.columnProps.label
                                                                    )
                                                            }
                                                        ]"
                                                        style="margin-right: 6px"
                                                    />
                                                    <el-checkbox
                                                        :label="element.columnProps.label"
                                                        :value="element.columnProps.label"
                                                    >
                                                        <div class="setting-checkbox__label">
                                                            <span>{{
                                                                element.columnProps.label
                                                            }}</span>
                                                        </div>
                                                    </el-checkbox>
                                                    <q-icon
                                                        v-show="
                                                            !excludeLabel[1].includes(
                                                                element.columnProps.label
                                                            )
                                                        "
                                                        :icon-class="element.fixed ? 'a-1' : 'a-2'"
                                                        size="14px"
                                                        :color="
                                                            element.fixed ? '#ff8713' : '#8c8c8c'
                                                        "
                                                        class-name="u-icon"
                                                        :class="{
                                                            'is-disabled':
                                                                affixChecked ||
                                                                !checkList.includes(
                                                                    element.columnProps?.label
                                                                ),
                                                            'is-show': element.fixed
                                                        }"
                                                        @mouseover="handleMouseOver(element)"
                                                        @mouseout="element.showTooltip = false"
                                                        @click="handleAffixItem(element)"
                                                    />
                                                    <transition name="fade">
                                                        <span
                                                            v-show="
                                                                !affixChecked &&
                                                                checkList.includes(
                                                                    element.columnProps?.label
                                                                ) &&
                                                                element.showTooltip
                                                            "
                                                            class="u-tooltip"
                                                            >{{
                                                                element.fixed
                                                                    ? '取消固定'
                                                                    : '固定标题'
                                                            }}</span
                                                        >
                                                    </transition>
                                                </div>
                                            </template>
                                        </draggable>
                                    </div>
                                </el-checkbox-group>
                            </div>
                        </div>
                    </el-popover>
                </div>
            </div>
        </div>
    </el-tooltip>
</template>

<script lang="ts">
import { CheckboxValueType } from 'element-plus';
import { PropType } from 'vue';
import useTool from './hooks/useTool';
import draggable from 'vuedraggable';
type List = Array<CheckboxValueType>;

let timer: any = null;
export default {
    name: 'TableTool',

    components: {
        draggable
    },

    props: {
        visible: {
            type: Boolean,
            default: false
        },
        showArrow: {
            type: Boolean,
            default: false
        },
        disabled: {
            type: Boolean
        },
        queryDom: {
            type: String,
            default: 'body'
        },

        placement: {
            type: String,
            default: 'bottom-end'
        },

        list: {
            type: Array as PropType<any[]>,
            default: () => []
        },

        defaultList: {
            type: Array as PropType<Readonly<any[]>>,
            default: () => []
        },

        tipContent: {
            type: String,
            default: '提示'
        }
    },

    emits: [
        'reset',
        'change',
        'moveChange',
        'affixChange',
        'columnChange',
        'affixItem',
        'update:visible'
    ],

    data() {
        return {
            isIndeterminate: false,
            checkAll: true,
            affixColumn: 1,
            affixChecked: false,
            checkList: [] as Array<string | number>,
            excludeLabel: ['序号', '操作'], // 排除 序号， 操作 列
            tableHeadList: this.getList(),
            thList: [],
            excludeLabels: [] as List
        };
    },

    computed: {
        columnList() {
            return this.tableHeadList.map((item: any) => item.columnProps.label);
        },

        max() {
            return this.tableHeadList.length;
        }
    },

    watch: {
        affixChecked(val: boolean) {
            if (val) {
                this.tableHeadList.map((item: any) => (item.fixed = false));
            }
            this.$emit('columnChange', this.affixColumn, val); // 通知表格更新
        }
    },

    setup(__, { emit }) {
        const { toolRef } = useTool(() => emit('update:visible', false));

        return {
            toolRef
        };
    },

    mounted() {
        this.getCheckList();
        document.addEventListener('click', this.handleClick);
    },

    onUnmounted() {
        // 销毁 tool
        this.$emit('update:visible', false);
        document.removeEventListener('click', this.handleClick);
    },

    methods: {
        getList() {
            return this.list.map((item, index) => ({ id: index, ...item }));
        },

        getCheckList() {
            this.checkList = this.columnList;
        },

        checkMove(evt: any) {
            const draggedContext = evt.draggedContext.element;
            const relatedContext = evt.relatedContext.element;

            return (
                !this.excludeLabel.includes(draggedContext.columnProps.label) && // 被拖拽元素不包含 序号，操作 列
                !this.excludeLabel.includes(relatedContext.columnProps.label) && // 所到达的元素不包含 序号，操作 列
                !relatedContext.fixed // 当前到达的元素不是固定元素
            );
        },

        handleVisible() {
            if (this.disabled) return;
            this.$emit('update:visible', !this.visible);
        },

        handleClick() {
            this.$emit('update:visible', false);
        },

        // 处理冻结列
        handleAffixColumn() {
            if (this.affixColumn == null) this.affixColumn = 1;
            if (!this.affixChecked) return;
            this.$emit('columnChange', this.affixColumn, this.affixChecked);
        },

        // 固定某列
        handleAffixItem(item: any) {
            if (this.affixChecked || !this.checkList.includes(item.columnProps.label)) return;
            item.fixed = !item.fixed;
            this.$emit('affixItem', item);
        },

        handleReset() {
            this.affixChecked = false;
            this.affixColumn = 1;
            this.excludeLabels = [];
            this.tableHeadList = this.getList();
            this.getCheckList();
            this.$emit('reset');
        },

        handleCheckedChange(value: List) {
            const checkedCount = value.length;
            const tableListLen = this.tableHeadList.length;
            this.checkAll = checkedCount === tableListLen;
            this.isIndeterminate = checkedCount > 0 && checkedCount < tableListLen;
            this.excludeLabels = [];
            this.tableHeadList.forEach((item: any) => {
                const index = value.findIndex(
                    (label: CheckboxValueType) => label === item.columnProps.label
                );
                if (index < 0) {
                    this.excludeLabels.push(item.columnProps.label);
                }

                // 重置所有固定列
                item.fixed = false;
            });

            this.$emit('change', this.excludeLabels);
        },

        handleDragChange(val: any) {
            this.tableHeadList.forEach((item: any) => (item.fixed = false));
            this.$emit('moveChange', val.moved);
        },

        handleMouseOver(element: any) {
            element.showTooltip = true;
            clearTimeout(timer);
            timer = setTimeout(() => {
                element.showTooltip = false;
            }, 2000);
        }
    }
};
</script>

<style lang="scss" scoped>
:deep() {
    .el-input-number {
        line-height: 20px;
    }

    .el-input-number .el-input__inner {
        text-align: center;
    }

    .el-input-number.is-without-controls .el-input__wrapper {
        padding: 0;
    }
}

.tool-box {
    display: flex;
    align-items: center;

    &--fixed {
        position: fixed;
        top: 135px;
        right: 40px;
        z-index: 13;
        transform: translateZ(0);
    }

    .tool-right {
        .custom-tooltip {
            height: 100%;
            padding: 0 8px;
            font-size: 20px;
            color: #434343;
            cursor: pointer;
        }
    }

    .tool-icon {
        box-sizing: border-box;
        height: 32px;
        line-height: 32px;
        background: #849dc41a;
        border: 1px solid var(--q-tool-color-border);
        border-radius: 4px;

        &:hover {
            color: var(--q-color-primary);
            background: var(--q-color-nav-hover);
            border-color: var(--q-tool-hover-border-color);

            .custom-tooltip {
                color: var(--q-color-primary);
            }
        }
    }
}

.setting-list {
    .setting-top {
        display: flex;
        align-items: center;
        padding: 13px 16px 10px;
        font-size: 14px;
        font-weight: 600;
        line-height: 14px;
        color: var(--q-text-color-primary);
        text-indent: 8px;

        &::before {
            position: relative;
            top: 1px;
            display: block;
            width: 2px;
            height: 14px;
            content: '';
            background: #06f;
            border-radius: 2px;
        }
    }
}

.setting-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 16px 3px;
    font-size: 14px;
    font-weight: 600;
    color: var(--q-text-color-primary);

    span {
        display: block;
        font-size: 12px;
        font-weight: 400;
        color: #06f;
        cursor: pointer;

        &:active {
            color: #1890ff;
        }
    }
}

.setting-checkbox--box {
    max-height: 300px;
    padding: 0 0 16px;
    overflow-y: auto;

    @include scrollbar_y(4px);
    @include scrollbar_x(6px);
    @include scrollbar_hover;
}

.setting-checkbox-group {
    .setting-checkbox-option {
        position: relative;
        display: flex;
        align-items: center;
        padding: 0 16px 0 23px;

        &:hover {
            .u-icon {
                display: block;
            }
        }
    }

    .setting-checkbox-icon {
        margin-right: 6px;
        font-size: 13px;
        color: rgb(223 222 222 / 100%);
    }
}

.setting-checkbox__label {
    display: flex;
    align-items: center;
}

.setting-affix {
    display: flex;
    align-items: center;
    padding-left: 29px;

    &__input {
        margin-left: 6px;
    }
}

.move {
    cursor: grab;
}

.unmove {
    cursor: not-allowed;
}

.u-icon {
    position: absolute;
    top: 10px;
    right: 6px;
    display: none;
    cursor: pointer;

    &.is-show {
        display: block;
    }
}

.u-tooltip {
    position: absolute;
    top: 30px;
    right: 6px;
    z-index: 11;
    width: auto;
    padding: 6px 10px;
    font-size: 12px;
    line-height: 20px;
    color: #fff;
    background: rgb(0 0 0 / 90%);
    border-radius: 4px;
}

.is-disabled {
    cursor: not-allowed !important;
}
</style>
